const STATUS = {
    PENDING: "pending",
    FULFILLED: "fulfilled",
    REJECTED: "rejected"
}

/**
 * 判断 x 是否为 Promise 类型，是则特殊处理
 * @param {*} promise 原 Promise 对象
 * @param {*} x 返回值
 * @param {*} resolve 成功回调
 * @param {*} reject 失败回调
 */
function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) {
        return new TypeError("Chaining cycle detected for promise #<MyPromise>")
    }

    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
        try {
            let then = x.then

            if (typeof then === 'function') {
                // Promise 认定条件
                then.call(x, (y) => {
                    resolve(y)
                }, (r) => {
                    reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            reject(e)
        }
    } else {
        resolve(x)
    }
}

class MyPromise {
    constructor(executor) {
        this.status = STATUS.PENDING
        this.value = undefined
        this.reason = undefined

        this.onFulfilledCallbacks = []
        this.onRejectedCallbacks = []

        const resolve = (value) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.FULFILLED
                this.value = value

                // 发布过程
                this.onFulfilledCallbacks.forEach(fn => fn())
            }

        }

        const reject = (reason) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.REJECTED
                this.reason = reason
            }

            this.onRejectedCallbacks.forEach(fn => fn())
        }

        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e)
        }

    }

    then(onFulfilled, onRejected) {
        let _promise = new MyPromise((resolve, reject) => {
            if (this.status === STATUS.FULFILLED) {
                setTimeout(() => { // 最小延迟 》 4ms
                    try {
                        let x = onFulfilled(this.value)
                        resolvePromise(_promise, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })

            }

            if (this.status === STATUS.REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(_promise, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })
            }

            // 异步处理
            if (this.status === STATUS.PENDING) {
                // 订阅过程(发布订阅模式)
                this.onFulfilledCallbacks.push(() => {
                    try {
                        let x = onFulfilled(this.value)
                        resolvePromise(_promise, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })

                this.onRejectedCallbacks.push(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(_promise, x, resolve, reject)

                    } catch (e) {
                        reject(e)
                    }
                })
            }
        })


        return _promise;
    }
}



module.exports = MyPromise;